/**
 * 2018年12月21日下午4:58:15
 * @author 谢进财
 */
package com.baihang.project.ds.webSocket.handler;

import java.io.IOException;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;

import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.Session;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import com.baihang.framework.kit.database.RedisKit;

import redis.clients.jedis.Jedis;

/**
 * @author whati
 *
 */
public class DsWebSocketHandler extends TextWebSocketHandler {
	private static final Logger logger = LoggerFactory.getLogger(DsWebSocketHandler.class);
	private static Map<String, Set<WebSocketSession>> userSocketSessionMap = new ConcurrentHashMap<>();
	private Jedis jedis = RedisKit.getJedis();
	public boolean closeCommond = false;//是否关闭每个session 项目结束时清空资源
	@Override
	public void afterConnectionEstablished(WebSocketSession session) throws Exception {		 
		String userName = (String) session.getAttributes().get("userName");
	        logger.info("Session {} connected.", userName);

	        // 如果是新 Session，记录进 Map
	        boolean isNewUser = true;
	        for (Entry<String, Set<WebSocketSession>> entry: userSocketSessionMap.entrySet()) {
	            String key = entry.getKey();
	            if (key.equals(userName)) {	            	
	            	userSocketSessionMap.get(userName).add(session);
	                isNewUser = false;
	                break;
	            }
	        }
	        if (isNewUser) {	           
	        	Set<WebSocketSession> sessions = new HashSet<>();
	            sessions.add(session);
	            userSocketSessionMap.put(userName, sessions);
	            jedis.sadd("zaixian", userName);
	        }
	        logger.info("当前在线用户数: {}", userSocketSessionMap.values().size());
	}

	
	@Override
	protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
		session.sendMessage(new TextMessage(String.format("{\"code\":\"%s\",\"result\":\"%s\"}","000","hello world")));   
		super.handleTextMessage(session, message);
	}

	@Override
	public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
		 	if (session.isOpen()) {
	            session.close();
	        }
	        // 移除Socket会话
	        for (Set<WebSocketSession> item : userSocketSessionMap.values()) {
	            if (item.contains(session)) {
	                // 删除连接 session
	                item.remove(session);
	                // 如果 userId 对应的 session 数为 0 ，删除该 userId 对应的记录
	                if (0 == item.size()) {
	                    userSocketSessionMap.values().remove(item);
	                    jedis.srem("zaixian",  (String) session.getAttributes().get("userName"));
	                    logger.info("手机号为{}的用户掉线了", (String) session.getAttributes().get("userName"));
	                }
	                break;
	            }
	        }
	        
	        logger.info("当前在线用户数: {}", userSocketSessionMap.values().size());
	}
	@Override
	public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
		 logger.info("Session {} disconnected. Because of {}", (String) session.getAttributes().get("userName"), status);
		 for (Set<WebSocketSession> item : userSocketSessionMap.values()) {
	            if (item.contains(session)) {
	                // 删除连接 session
	                item.remove(session);
	                // 如果 userId 对应的 session 数为 0 ，删除该 userId 对应的记录
	                if (0 == item.size()) {
	                    userSocketSessionMap.values().remove(item);
	                    jedis.srem("zaixian",  (String) session.getAttributes().get("userName"));
	                    logger.info("手机号为{}的用户关闭了连接", (String) session.getAttributes().get("userName"));
	                }
	                break;
	            }
	        }
	        
		 logger.info("当前在线用户数: {}", userSocketSessionMap.values().size());
	}


    /**
     * 给所有在线用户发送消息
     *
     * @param message
     * @throws IOException
     */
    public void broadcast(final TextMessage message) throws IOException {
    	//System.err.println("群发");
        // 多线程群发
    	ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1,
    			new BasicThreadFactory.Builder().namingPattern("socket-schedule-pool-%d").daemon(true).build());    	
    	for(Set<WebSocketSession> item : userSocketSessionMap.values()) {//遍历用户
    		for (final WebSocketSession session : item) {//遍历每个用户中的session
                if (session.isOpen()) {
                        executorService.execute(new Runnable() {
                            @Override
                            public void run() {
                                try {
                                    if (session.isOpen()) {
                                        //logger.debug("broadcast output:" + message.toString());
                                        session.sendMessage(message);
                                        
                                    }
                                } catch (IOException e) {
                                    e.printStackTrace();
                                }
                            }
                        });
                  
                }
    		}
        }
    }

    /**
     * 给某个用户发送消息
     *
     * @param userName
     * @param message
     * @throws IOException
     */
    public void sendMessageToUser(String userName, TextMessage message) throws IOException {
    	logger.info("手机号为{}的用户被推送消息!",userName);
    	Set<WebSocketSession> item = userSocketSessionMap.get(userName);
    	ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1,
    			new BasicThreadFactory.Builder().namingPattern("socket-schedule-pool-%d").daemon(true).build());
    	for (final WebSocketSession session : item) {//遍历每个用户中的session
            if (session.isOpen()) {
              
                    executorService.execute(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                if (session.isOpen()) {
                                    session.sendMessage(message);
                                    if(closeCommond) {
                                    	session.close();
                                    }
                                }
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    });
              
            }
		}
    }
   
}
